package com.beiding.businessplatform.request;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.beiding.businessplatform.data.Vm;
import com.example.demo.auto.model.A;

import java.util.List;
import java.util.Map;

public class Requester<V extends Vm> {

    //默认返回
    private R r = R.OK;

    //请求体
    private final String body;

    //请求体和默认vm类型是不可变的
    private Class<V> defaultVmType;

    //请求体
    private CacheBody cacheBody;

    public Requester(String body) {
        if (body == null) {
            E.badRequest("缺少必要参数:" + this.getClass());
        }
        this.body = body;
        this.defaultVmType = null;
    }

    public Requester(String body, Class<V> vmType) {
        if (body == null) {
            E.badRequest("缺少必要参数:" + this.getClass());
        }
        this.defaultVmType = vmType;
        this.body = body;
    }

    public String getBody() {
        return body;
    }

    //vm类型
    public Class<V> getDefaultVmType() {
        return defaultVmType;
    }

    //设置返回
    public void setR(R r) {
        this.r = r;
    }

    public R getR() {
        return r;
    }

    //使用默认的vm类型格式化请求体
    public V toVm() {
        if (defaultVmType == null) {
            E.error("未给定默认的视图模型类型,不支持该操作");
        }

        if (this.cacheBody == null) {
            this.cacheBody = new CacheBody();
        } else {
            if (cacheBody.vm != null) {
                return cacheBody.vm;
            }
        }

        V v = toVm(defaultVmType);
        this.cacheBody.vm = v;
        return v;
    }

    //复制
    public Requester<V> copy() {
        return new Requester<>(this.body, this.defaultVmType);
    }

    //复制为新的vm类型
    public <NT extends Vm> Requester copy(Class<NT> nt) {
        return new Requester<>(this.body, nt);
    }

    //请求体可以格式化为任意的视图模型
    public <T extends Vm> T toVm(Class<T> type) {

        try {
            return JSON.parseObject(body, type);
        } catch (Exception e) {
            E.error("请求体解析失败:" + e.getMessage());
            return null;
        }
    }

    public <T extends Vm> Requester<T> getRequester(String key,Class<T> type) {
        String jsonText = getJsonText(key);
        if (jsonText == null) {
            return null;
        }
        return new Requester<T>(jsonText, type);
    }

    public <T extends Vm> Requester<T> requireRequester(String key,Class<T> type) {
        String jsonText = requireJsonText(key);
        return new Requester<T>(jsonText, type);
    }

    public <T extends Vm> T getVm(String key,Class<T> type) {
        String jsonText = getJsonText(key);
        if (jsonText == null) {
            return null;
        }
        try {
            return JSON.parseObject(jsonText, type);
        } catch (Exception e) {
            E.error("请求体解析失败:" + e.getMessage());
            return null;
        }
    }

    public <T extends Vm> T requireVm(String key,Class<T> type) {
        String jsonText = requireJsonText(key);
        try {
            return JSON.parseObject(jsonText, type);
        } catch (Exception e) {
            E.error("请求体解析失败:" + e.getMessage());
            return null;
        }
    }



    public Map<String, Object> toMap() {

        try {
            if (cacheBody == null) {
                this.cacheBody = new CacheBody();
            } else {
                if (this.cacheBody.map != null) {
                    return this.cacheBody.map;
                }
            }
            this.cacheBody.map = (JSONObject) JSON.parse(body);
            return this.cacheBody.map;
        } catch (Exception e) {
            E.error("请求解析失败:" + e.getMessage());
            return null;
        }
    }

    /****封装取值操作***/

    public Object get(String key) {
        return toMap().get(key);
    }

    public Object require(String key) {
        return require(key, Object.class);
    }

    public <T> T get(String key, Class<T> type) {
        toMap();
        return cacheBody.map.getObject(key, type);
    }

    public <T> T require(String key, Class<T> type) {
        T object = get(key, type);
        if (object == null) {
            E.badRequest("缺少必要的参数:" + key);
        }
        return object;
    }

    public List getList(String key) {
        return get(key, List.class);
    }

    public Map getMap(String key) {
        return get(key, Map.class);
    }

    public List requireList(String key) {
        return require(key, List.class);
    }

    public Map requireMap(String key) {
        return require(key, Map.class);
    }

    public String requireString(String key) {
        return require(key, String.class);
    }

    public Integer requireInteger(String key) {
        return require(key, Integer.class);
    }

    public Long requireLong(String key) {
        return require(key, Long.class);
    }

    public Double requireDouble(String key) {
        return require(key, Double.class);
    }

    public Character requireCharacter(String key) {
        return require(key, Character.class);
    }

    public Boolean requireBoolean(String key) {
        return require(key, Boolean.class);
    }

    public Float requireFloat(String key) {
        return require(key, Float.class);
    }

    public Byte requireByte(String key) {
        return require(key, Byte.class);
    }

    public Short requireShort(String key) {
        return require(key, Short.class);
    }


    public String getString(String key) {
        return get(key, String.class);
    }

    public Integer getInteger(String key) {
        return get(key, Integer.class);
    }

    public Long getLong(String key) {
        return get(key, Long.class);
    }

    public Double getDouble(String key) {
        return get(key, Double.class);
    }

    public Character getCharacter(String key) {
        return get(key, Character.class);
    }

    public Boolean getBoolean(String key) {
        return get(key, Boolean.class);
    }

    public Float getFloat(String key) {
        return get(key, Float.class);
    }

    public Byte getByte(String key) {
        return get(key, Byte.class);
    }

    public Short getShort(String key) {
        return get(key, Short.class);
    }


    public String getJsonText(String key) {
        Object o = get(key);
        if (o == null) {
            return null;
        }
        return JSON.toJSONString(o);
    }

    public String requireJsonText(String key) {
        Object o = require(key);
        return JSON.toJSONString(o);
    }


    /***封装常见响应***/

    public void ok(Object body) {
        r = R.ok(body);
    }

    public void warning(String msg) {
        r = R.warning(msg);
    }

    public void error(String msg) {
        r = R.error(msg);
    }

    private class CacheBody {
        private V vm;
        private JSONObject map;
    }

}
